package cn.edu.zut.soft.graduate.websocket;

import cn.edu.zut.soft.graduate.core.vo.LoginVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author cc
 * @Date 2016/11/15
 * @value 1.0
 */
@Component
public class UserMonitoringHandler implements WebSocketHandler {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    private static final String USER = "user";

    public static final Map<Integer,WebSocketSession> userSocketSessionMap;

    static {
        userSocketSessionMap = new ConcurrentHashMap<>();
    }

    /**
     * 建立连接
     * @param webSocketSession
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        LoginVO loginVO = (LoginVO) webSocketSession.getAttributes().get(USER);
        if (userSocketSessionMap.get(loginVO.getId()) == null){
            userSocketSessionMap.put(loginVO.getId(),webSocketSession);
        }
        logger.info("Socket 会话建立连接 id = " + loginVO.getId() + ",name = " + loginVO.getName());
    }

    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {

    }

    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        if (webSocketSession.isOpen()){
            webSocketSession.close();
        }
        Iterator<Map.Entry<Integer, WebSocketSession>> it = userSocketSessionMap
                .entrySet().iterator();
        logger.info(throwable.getMessage());
        removeSocketSession(webSocketSession, it);
    }

    /**
     * 移除WebSocketSession
     * @param webSocketSession
     * @param it
     */
    private void removeSocketSession(WebSocketSession webSocketSession, Iterator<Map.Entry<Integer, WebSocketSession>> it) {
        // 移除Socket会话
        while (it.hasNext()) {
            Map.Entry<Integer, WebSocketSession> entry = it.next();
            if (entry.getValue().getId().equals(webSocketSession.getId())) {
                userSocketSessionMap.remove(entry.getKey());
                logger.info("Socket会话已经移除:用户ID" + entry.getKey());
                break;
            }
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        Iterator<Map.Entry<Integer, WebSocketSession>> it = userSocketSessionMap
                .entrySet().iterator();
        logger.info("Socket会话断开");
        removeSocketSession(webSocketSession, it);
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }


    /**
     * 给所有在线用户发送消息
     *
     * @param message
     * @throws IOException
     */
    public void broadcast(final TextMessage message) throws IOException {
        // 多线程群发
        for (final Map.Entry<Integer, WebSocketSession> entry : userSocketSessionMap
                .entrySet()) {
            if (entry.getValue().isOpen()) {
                // entry.getValue().sendMessage(message);
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            if (entry.getValue().isOpen()) {
                                entry.getValue().sendMessage(message);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }

        }
    }

    /**
     * 给某个用户发送消息
     * @param message
     * @throws IOException
     */
    public void sendMessageToUser(Integer id, TextMessage message)
            throws IOException {
        WebSocketSession session = userSocketSessionMap.get(id);
        if (session != null && session.isOpen()) {
            session.sendMessage(message);
        }
    }

}
